﻿using System;
using System.IO;
using FunctionalCLR.Core;
using System.Collections.Generic;

namespace Zove.Runtime {
    /// <summary>
    /// Finds the designated file of the given class.
    /// </summary>
    public class DefaultClassFinder : IClassFinder {

        private List<string> workspaces = new List<string>();

        /// <summary>
        /// constructor
        /// </summary>
        public DefaultClassFinder() {
            string[] s = Utils.ModelPath.Split(';');
            this.workspaces.AddRange(s);
        }

        /// <summary>
        /// constructor with the workspace
        /// </summary>
        /// <param name="workspace"></param>
        public DefaultClassFinder(string workspace) : this() {
            string[] s = workspace.Split(';');
            this.workspaces.AddRange(s);
        }

        /// <summary>
        /// add workspace to class finder
        /// </summary>
        /// <param name="workspace"></param>
        public void AddWorkspace(string workspace) {
            workspaces.Add(workspace);
        }

        /// <summary>
        /// get all workspaces
        /// </summary>
        /// <returns></returns>
        public string[] GetAllWorkspaces() {
            return this.workspaces.ToArray();
        }

        #region IClassFinder Members

        /// <summary>
        /// Gets the location of the class.
        /// </summary>
        /// <param name="className">the class name</param>
        /// <returns>the file location</returns>
        public string GetLocation(string className) {
            string fileName = className + ".zoom";
            if (File.Exists(fileName)) {
                return fileName;
            }

            if (string.IsNullOrEmpty(Utils.ModelPath)) {
                throw new FileNotFoundException(fileName);
            }

            foreach (string cp in this.workspaces) {
                DirectoryInfo di = new DirectoryInfo(cp);
                string fullFileName = Find(di, fileName);

                if (!string.IsNullOrEmpty(fullFileName)) {
                    return fullFileName;
                }
            }

            return string.Empty;
        }

        /// <summary>
        /// Iteratively finds class over directories;
        /// </summary>
        /// <param name="di"></param>
        /// <param name="fileName"></param>
        /// <returns></returns>
        public string Find(DirectoryInfo di, string fileName) {
            if (di.Name == ".svn")
            {
                return string.Empty;
            }

            foreach (FileInfo fi in di.GetFiles()) {
                if (string.Compare(
                    fi.Name, fileName, StringComparison.CurrentCultureIgnoreCase) == 0) {
                    return fi.FullName;
                }
            }

            foreach (DirectoryInfo sdi in di.GetDirectories()) {
                string found = this.Find(sdi, fileName);
                if (!string.IsNullOrEmpty(found)) {
                    return found;
                }
            }

            return string.Empty;
        }

        #endregion
    }
}
